home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / sipp / libsipp / strauss.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-03  |  5.8 KB  |  167 lines

  1. /**
  2.  ** sipp - SImple Polygon Processor
  3.  **
  4.  **  A general 3d graphic package
  5.  **
  6.  **  Copyright Equivalent Software HB  1992
  7.  **
  8.  ** This program is free software; you can redistribute it and/or modify
  9.  ** it under the terms of the GNU General Public License as published by
  10.  ** the Free Software Foundation; either version 1, or any later version.
  11.  ** This program is distributed in the hope that it will be useful,
  12.  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  ** GNU General Public License for more details.
  15.  ** You can receive a copy of the GNU General Public License from the
  16.  ** Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  **/
  18.  
  19. /**
  20.  ** strauss.c - Shading model designed by Paul S. Strauss
  21.  **             Silicon Graphics Inc.
  22.  **             Described in IEEE CG&A November 1990.
  23.  **
  24.  **             Implemented for SIPP by Jonas Yngvesson
  25.  **/
  26.  
  27. #include <math.h>
  28.  
  29. #include <sipp.h>
  30. #include <shaders.h>
  31. #include <geometric.h>
  32.  
  33.  
  34. /*
  35.  * Strauss describes, in his article, two functions that simulates
  36.  * fresnel reflection and geometric attenuation. These functions
  37.  * are dependent of an angle between 0 and pi/2 normalized to the 
  38.  * range (0.0, 1.0). He also mentions that he uses versions of the
  39.  * functions that depend on the cosine of an angle instead (since 
  40.  * that can be calculated with a dot product).
  41.  * These versions are not described in the article so I have empirically 
  42.  * tried to recreate them. I don't know if this bears any resemblence
  43.  * to what he used, so any errors are my fault.
  44.  *
  45.  * What i did was only to change x in the functions to (1 - x) and modify
  46.  * the Kf and Kg constants slightly. The original values in the article
  47.  * was: Kf = 1.12, Kg = 1.02
  48.  */
  49.  
  50. #define Kf   1.2   /* Factor used in approximation of fresnel reflection */
  51. #define Kg   1.031 /* Factor used in approximation of geometric attenuation */
  52.  
  53.  
  54. /*
  55.  * Function to simulate fresnel reflection.
  56.  */
  57. #define FR(x) ((1.0/((1.0-(x)-Kf)*(1.0-(x)-Kf))-1.0/(Kf*Kf))\
  58.                /(1.0/((1.0-Kf)*(1.0-Kf))-1.0/(Kf*Kf)))
  59.  
  60. /*
  61.  * Function to simulate geometric attenuation.
  62.  */
  63. #define GA(x) ((1.0/((1.0-Kg)*(1.0-Kg))-1.0/((1.0-(x)-Kg)*(1.0-(x)-Kg)))\
  64.                /(1.0/((1.0-Kg)*(1.0-Kg))-1.0/(Kg*Kg)))
  65.  
  66.  
  67.  
  68. void
  69. strauss_shader(pos, normal, texture, view_vec, lights, sd, color, opacity)
  70.     Vector        *pos;
  71.     Vector        *normal;
  72.     Vector        *texture;
  73.     Vector        *view_vec;
  74.     Lightsource   *lights;
  75.     Strauss_desc  *sd;
  76.     Color         *color;
  77.     Color         *opacity;
  78. {
  79.     Vector       unit_normal;  /* Normalized surface normal */
  80.     Vector       highlight;    /* Highlight vector */
  81.     double       c_alpha;      /* cos(angle between normal and lightvector) */
  82.     double       c_beta;       /* cos(angle between highlight & view_vec) */
  83.     double       c_gamma;      /* cos(angle between normal & view_vec) */
  84.     double       rd;           /* Diffuse reflectivity */
  85.     double       rs;           /* Specular reflectivity */
  86.     double       rj;           /* Adjusted specular reflectivity */
  87.     double       rn;           /* Specular reflectivity at normal incidence */
  88.     double       h;            /* Shininess exponent */
  89.     Vector       qd;           /* Diffuse reflection factor */
  90.     Vector       qs;           /* Specular reflection factor */
  91.     Vector       light_dir;    /* Direction to "current" light */
  92.     double       light_factor; /* Fraction of light from "current" light */
  93.     Color        col;          /* Resulting color */
  94.     Lightsource *lp;
  95.  
  96.     VecCopy(unit_normal, *normal);
  97.     vecnorm(&unit_normal);
  98.     c_gamma = VecDot(unit_normal, *view_vec);
  99.     col.red = col.grn = col.blu = 0.0;
  100.     rd = 1.0 - sd->smoothness * sd->smoothness * sd->smoothness;
  101.  
  102.     for (lp = lights; lp != (Lightsource *)0; lp = lp->next) {
  103.  
  104.         light_factor = light_eval(lp, pos, &light_dir);
  105.  
  106.         c_alpha = VecDot(unit_normal, light_dir);
  107.  
  108.         if (c_alpha >= 0) {
  109.  
  110.             VecScalMul(highlight, 2 * c_alpha, unit_normal);
  111.             VecSub(highlight, highlight, light_dir);
  112.             c_beta = VecDot(highlight, *view_vec);
  113.             
  114.             MakeVector(qd, sd->color.red, sd->color.grn, sd->color.blu);
  115.             VecScalMul(qd, (c_alpha * rd 
  116.                             * (1.0 - sd->metalness * sd->smoothness)), qd);
  117.             
  118.             if (c_beta >= 0) {
  119.                 
  120.                 h = 3 / (1.0 - sd->smoothness);
  121.                 rn = 1.0 - rd;
  122.                 rj = rn + (rn + 0.1) * FR(c_alpha) * GA(c_alpha) * GA(c_gamma);
  123.                 if (rj > 1.0) {
  124.                     rj = 1.0;
  125.                 }
  126.                 rs = exp(h * log(c_beta)) * rj;
  127.                 
  128.                 MakeVector(qs, 
  129.                            sd->color.red - 1.0, 
  130.                            sd->color.grn - 1.0, 
  131.                            sd->color.blu - 1.0);
  132.                 VecScalMul(qs, sd->metalness * (1.0 - FR(c_alpha)), qs);
  133.                 qs.x += 1.0;
  134.                 qs.y += 1.0;
  135.                 qs.z += 1.0;
  136.                 
  137.                 VecScalMul(qs, rs, qs);
  138.                 VecAdd(qd, qd, qs);
  139.  
  140.             }
  141.             
  142. /*            VecScalMul(qd, lp->intensity, qd);*/
  143.  
  144.             qd.x = lp->color.red * qd.x;
  145.             qd.y = lp->color.grn * qd.y;
  146.             qd.z = lp->color.blu * qd.z;
  147.             
  148.             col.red += qd.x;
  149.             col.grn += qd.y;
  150.             col.blu += qd.z;
  151.  
  152.         }
  153.     }
  154.  
  155.     col.red += sd->ambient * rd * sd->color.red;
  156.     col.grn += sd->ambient * rd * sd->color.grn;
  157.     col.blu += sd->ambient * rd * sd->color.blu;
  158.  
  159.     color->red = ((col.red > 1.0) ? 1.0 : col.red);
  160.     color->grn = ((col.grn > 1.0) ? 1.0 : col.grn);
  161.     color->blu = ((col.blu > 1.0) ? 1.0 : col.blu);
  162.  
  163.     opacity->red = sd->opacity.red;
  164.     opacity->grn = sd->opacity.grn;
  165.     opacity->blu = sd->opacity.blu;
  166. }
  167.